package com.xbongbong.paas.lowcode.impl;

import com.alibaba.fastjson.JSON;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.lowcode.CustomButtonService;
import com.xbongbong.paas.model.CustomButtonActionModel;
import com.xbongbong.paas.model.CustomButtonModel;
import com.xbongbong.paas.pojo.ButtonPojo;
import com.xbongbong.paas.pojo.WorkFlowPojo;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.pro.custombutton.pojo.CustomButtonActionPojo;
import com.xbongbong.pro.custombutton.pojo.CustomButtonPojo;
import com.xbongbong.pro.custombutton.pojo.dto.CustomButtonListDTO;
import com.xbongbong.pro.custombutton.pojo.dto.CustomButtonSaveDTO;
import com.xbongbong.pro.custombutton.pojo.vo.CustomButtonListVO;
import com.xbongbong.pro.custombutton.pojo.vo.CustomButtonSaveVO;
import com.xbongbong.pro.domain.entity.CustomButtonActionEntity;
import com.xbongbong.pro.domain.entity.CustomButtonEntity;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.lowcode.ButtonTypeEnum;
import com.xbongbong.pro.enums.lowcode.LowCodeActionTypeEnum;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author 吴峰
 * @date 2021/03/04 21:25
 */
@Service("customButtonService")
public class CustomButtonServiceImpl implements CustomButtonService {

    private static final Logger LOG = LoggerFactory.getLogger(CustomButtonServiceImpl.class);

    @Resource
    private CustomButtonModel customButtonModel;
    @Resource
    private CustomButtonActionModel customButtonActionModel;

    @Override
    public CustomButtonListVO list(CustomButtonListDTO customButtonListDTO) throws XbbException {
        CustomButtonListVO customButtonListVO = new CustomButtonListVO();
        try {
            String corpid = customButtonListDTO.getCorpid();
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(StringConstant.FORM_ID, customButtonListDTO.getFormId());
            param.put(StringConstant.BUSINESS_TYPE, customButtonListDTO.getBusinessType());
            param.put("type", customButtonListDTO.getType());
            List<CustomButtonEntity> buttonList = customButtonModel.findEntitys(param);
            if (CollectionsUtil.isEmpty(buttonList)) {
                customButtonListVO.setCustomButtonList(new ArrayList<>());
                return customButtonListVO;
            }
            Set<Long> buttonIdList = new HashSet<>();
            buttonList.forEach(item->buttonIdList.add(item.getId()));
            Map<Long, List<CustomButtonActionPojo>> actionMap = new HashMap<>(buttonList.size());
            List<CustomButtonPojo> customButtonList = new ArrayList<>();
            param.clear();
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(StringConstant.FORM_ID, customButtonListDTO.getFormId());
            param.put(StringConstant.BUSINESS_TYPE, customButtonListDTO.getBusinessType());
            param.put("buttonIdIn", buttonIdList);
            List<CustomButtonActionEntity> buttonActionList = customButtonActionModel.findEntitys(param);
            buttonActionList.forEach(item->{
                if (actionMap.containsKey(item.getButtonId())) {
                    List<CustomButtonActionPojo> customButtonActionList = actionMap.get(item.getButtonId());
                    CustomButtonActionPojo customButtonActionPojo = new CustomButtonActionPojo(item.getId(), item.getButtonId(), item.getActionType(), JSON.parseObject(item.getParam()), item.getSort());
                    customButtonActionList.add(customButtonActionPojo);
                    actionMap.put(item.getButtonId(), customButtonActionList);
                } else {
                    List<CustomButtonActionPojo> customButtonActionList = new ArrayList<>();
                    CustomButtonActionPojo customButtonActionPojo = new CustomButtonActionPojo(item.getId(), item.getButtonId(), item.getActionType(), JSON.parseObject(item.getParam()), item.getSort());
                    customButtonActionList.add(customButtonActionPojo);
                    actionMap.put(item.getButtonId(), customButtonActionList);
                }
            });
            buttonList.forEach(item->{
                CustomButtonPojo customButtonPojo = new CustomButtonPojo(item.getId(), item.getName(), item.getIcon(), item.getColor(), item.getType(), item.getSort(), actionMap.get(item.getId()));
                customButtonList.add(customButtonPojo);
            });
            customButtonListVO.setCustomButtonList(customButtonList);
        } catch (Exception e) {
            LOG.error("CustomButtonServiceImpl.list error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return customButtonListVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CustomButtonSaveVO add(CustomButtonSaveDTO customButtonSaveDTO) throws XbbException {
        CustomButtonSaveVO customButtonSaveVO = new CustomButtonSaveVO();
        try {
            String corpid = customButtonSaveDTO.getCorpid();
            Long formId = customButtonSaveDTO.getFormId();
            Integer saasMark = customButtonSaveDTO.getSaasMark();
            Integer businessType = customButtonSaveDTO.getBusinessType();
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(StringConstant.BUSINESS_TYPE, businessType);
            param.put(StringConstant.FORM_ID, formId);
            List<CustomButtonEntity> buttonList = customButtonModel.findEntitys(param);
            List<Long> deleteIdList = new ArrayList<>();
            buttonList.forEach(item->{
                deleteIdList.add(item.getId());
            });
            String userId = customButtonSaveDTO.getUserId();
            List<CustomButtonPojo> customButtonList = customButtonSaveDTO.getCustomButtonList();
            List<CustomButtonEntity> addList = new ArrayList<>();
            List<CustomButtonEntity> updateList = new ArrayList<>();
            List<Long> updateIdList = new ArrayList<>();
            List<CustomButtonActionEntity> actionAddList = new ArrayList<>();
            List<CustomButtonActionEntity> actionUpdateList = new ArrayList<>();
            List<Long> updateActionIdList = new ArrayList<>();
            for (CustomButtonPojo customButton : customButtonList) {

                if (Objects.isNull(customButton.getId())) {
                    long now = DateTimeUtil.getInt();
                    List<CustomButtonActionEntity> actionList = new ArrayList<>();
                    CustomButtonEntity customButtonEntity = new CustomButtonEntity(corpid, formId, saasMark, businessType, customButton.getName(), customButton.getIcon(), customButton.getColor(),
                            customButton.getType(), customButton.getSort(), userId, now, now);
                    customButton.getActionList().forEach(action->{
                        Long serviceId = 0L;
                        if (Objects.equals(LowCodeActionTypeEnum.API_SERVICE.getCode(), action.getActionType())
                                || Objects.equals(LowCodeActionTypeEnum.INITIATE_REQUEST.getCode(), action.getActionType())) {
                            serviceId = action.getParam().getLong("serviceId");
                        }
                        CustomButtonActionEntity customButtonActionEntity = new CustomButtonActionEntity(corpid, formId, saasMark, businessType,  0L, action.getActionType(), serviceId,
                                JSON.toJSONString(action.getParam()), action.getSort(), userId, now, now);
                        actionList.add(customButtonActionEntity);
                    });
                    customButtonEntity.setActionList(actionList);
                    addList.add(customButtonEntity);
                } else {
                    long now = DateTimeUtil.getInt();
                    CustomButtonEntity customButtonEntity = new CustomButtonEntity( customButton.getId(), customButton.getName(), customButton.getIcon(), customButton.getColor(),
                            customButton.getType(), customButton.getSort(), now);
                    customButton.getActionList().forEach(action->{
                        Long serviceId = 0L;
                        if (Objects.equals(LowCodeActionTypeEnum.API_SERVICE.getCode(), action.getActionType())
                                || Objects.equals(LowCodeActionTypeEnum.INITIATE_REQUEST.getCode(), action.getActionType())) {
                            serviceId = action.getParam().getLong("serviceId");
                        }
                        if (Objects.isNull(action.getId())) {
                            CustomButtonActionEntity customButtonActionEntity = new CustomButtonActionEntity(corpid, formId, saasMark, businessType,  customButton.getId(), action.getActionType(), serviceId,
                                    JSON.toJSONString(action.getParam()), action.getSort(), userId, now, now);
                            actionAddList.add(customButtonActionEntity);
                        } else {
                            CustomButtonActionEntity customButtonActionEntity = new CustomButtonActionEntity(action.getId(), action.getActionType(), serviceId,
                                    JSON.toJSONString(action.getParam()), action.getSort(),  now);
                            actionUpdateList.add(customButtonActionEntity);
                            updateActionIdList.add(action.getId());
                        }
                    });
                    updateList.add(customButtonEntity);
                    updateIdList.add(customButton.getId());
                }
            }
            deleteIdList.removeAll(updateIdList);
            param.clear();
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(StringConstant.FORM_ID, formId);
            param.put(StringConstant.BUSINESS_TYPE, businessType);
            List<CustomButtonActionEntity> buttonActionList = customButtonActionModel.findEntitys(param);
            List<Long> deleteActionIdList= new ArrayList<>();
            buttonActionList.forEach(item->{
                deleteActionIdList.add(item.getId());
            });
            deleteActionIdList.removeAll(updateActionIdList);
            if (CollectionsUtil.isNotEmpty(addList)) {
                customButtonModel.insertBatch(addList);
                addList.forEach(item->{
                    item.getActionList().forEach(action->{
                        action.setButtonId(item.getId());
                        actionAddList.add(action);
                    });
                });
            }
            if (CollectionsUtil.isNotEmpty(updateList)) {
                customButtonModel.updateBatch(updateList, corpid);
            }
            if (CollectionsUtil.isNotEmpty(deleteIdList)) {
                customButtonModel.deleteBatch(deleteIdList, corpid);
            }
            if (CollectionsUtil.isNotEmpty(actionAddList)) {
                customButtonActionModel.insertBatch(actionAddList);
            }
            if (CollectionsUtil.isNotEmpty(actionUpdateList)) {
                customButtonActionModel.updateBatch(actionUpdateList, corpid);
            }
            if (CollectionsUtil.isNotEmpty(deleteActionIdList)) {
                customButtonActionModel.deleteBatch(deleteActionIdList, corpid);
            }
        } catch (Exception e) {
            LOG.error("CustomButtonServiceImpl.add error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return customButtonSaveVO;
    }

    @Override
    public CustomButtonListVO listByPermission(CustomButtonListDTO customButtonListDTO) throws XbbException {
        CustomButtonListVO customButtonListVO = new CustomButtonListVO();
        try {
            customButtonListVO = list(customButtonListDTO);
            // TODO 需要增加权限
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("CustomButtonServiceImpl.add error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return customButtonListVO;
    }

    @Override
    public List<WorkFlowPojo> getButtonList(Integer businessType, Long formId, Integer saasMark, String corpid, UserVO userVO, Integer type) throws XbbException {
        // 低代码按钮
        CustomButtonListDTO customButtonListDTO = new CustomButtonListDTO();
        customButtonListDTO.setBusinessType(businessType);
        customButtonListDTO.setFormId(formId);
        customButtonListDTO.setSaasMark(saasMark);
        customButtonListDTO.setCorpid(corpid);
        customButtonListDTO.setLoginUser(userVO);
        customButtonListDTO.setType(type);
        List<WorkFlowPojo> workFlowPojoList = new ArrayList<>();
        CustomButtonListVO formCustomButtonListVO = listByPermission(customButtonListDTO);
        if (Objects.nonNull(formCustomButtonListVO) && CollectionsUtil.isNotEmpty(formCustomButtonListVO.getCustomButtonList())) {
            formCustomButtonListVO.getCustomButtonList().forEach(item->{
                WorkFlowPojo buttonPojo = new WorkFlowPojo();
                buttonPojo.setActionList(item.getActionList());
                buttonPojo.setValue(item.getName());
                buttonPojo.setAttr(PaasConstant.LOW_CODE);
                buttonPojo.setId(PaasConstant.LOW_CODE+StringConstant.UNDER_LINE+item.getId());
                workFlowPojoList.add(buttonPojo);
            });
        }
        return workFlowPojoList;
    }

    @Override
    public List<ButtonPojo> getLowCodeButtonList(Integer businessType, Integer subBusinessType, Long formId, Integer saasMark, String corpid, UserVO userVO, Integer type) throws XbbException {
        // 待系列businesstype特殊处理
        CustomButtonListDTO customButtonListDTO = new CustomButtonListDTO();
        customButtonListDTO.setBusinessType(businessType);
        if ((Objects.equals(XbbRefTypeEnum.PRODUCT.getCode(),businessType) || Objects.equals(XbbRefTypeEnum.CONTRACT.getCode(),businessType)) && Objects.equals(XbbRefTypeEnum.WAIT_PURCHASE.getCode(),subBusinessType)){
            customButtonListDTO.setBusinessType(XbbRefTypeEnum.WAIT_PURCHASE.getCode());
        }

        customButtonListDTO.setFormId(formId);
        customButtonListDTO.setSaasMark(saasMark);
        customButtonListDTO.setCorpid(corpid);
        customButtonListDTO.setLoginUser(userVO);
        customButtonListDTO.setType(ButtonTypeEnum.LIST.getCode());
        CustomButtonListVO formCustomButtonListVO = listByPermission(customButtonListDTO);
        List<ButtonPojo> list = new ArrayList<>();
        if (Objects.nonNull(formCustomButtonListVO) && CollectionsUtil.isNotEmpty(formCustomButtonListVO.getCustomButtonList())) {
            formCustomButtonListVO.getCustomButtonList().forEach(item->{
                ButtonPojo buttonPojo = new ButtonPojo();
                buttonPojo.setActionList(item.getActionList());
                buttonPojo.setValue(item.getName());
                buttonPojo.setAttr(PaasConstant.LOW_CODE);
                list.add(buttonPojo);
            });
        }
        return list;
    }
}
